<html><head><meta charset="utf-8"><title>21 索引类型：获取索引类型和索引值类型-慕课专栏</title>
			<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
			<meta name="renderer" content="webkit">
			<meta property="qc:admins" content="77103107776157736375">
			<meta property="wb:webmaster" content="c4f857219bfae3cb">
			<meta http-equiv="Access-Control-Allow-Origin" content="*">
			<meta http-equiv="Cache-Control" content="no-transform ">
			<meta http-equiv="Cache-Control" content="no-siteapp">
			<link rel="apple-touch-icon" sizes="76x76" href="https://www.imooc.com/static/img/common/touch-icon-ipad.png">
			<link rel="apple-touch-icon" sizes="120x120" href="https://www.imooc.com/static/img/common/touch-icon-iphone-retina.png">
			<link rel="apple-touch-icon" sizes="152x152" href="https://www.imooc.com/static/img/common/touch-icon-ipad-retina.png">
			<link href="https://moco.imooc.com/captcha/style/captcha.min.css" rel="stylesheet">
			<link rel="stylesheet" href="https://www.imooc.com/static/moco/v1.0/dist/css/moco.min.css?t=201907021539" type="text/css">
			<link rel="stylesheet" href="https://www.imooc.com/static/lib/swiper/swiper-3.4.2.min.css?t=201907021539">
			<link rel="stylesheet" href="https://static.mukewang.com/static/css/??base.css,common/common-less.css?t=2.5,column/zhuanlanChapter-less.css?t=2.5,course/inc/course_tipoff-less.css?t=2.5?v=201907051055" type="text/css">
			<link charset="utf-8" rel="stylesheet" href="https://www.imooc.com/static/lib/ueditor/themes/imooc/css/ueditor.css?v=201907021539"><link rel="stylesheet" href="https://www.imooc.com/static/lib/baiduShare/api/css/share_style0_16.css?v=6aba13f0.css"></head>
			<body><div id="main">

<div class="container clearfix" id="top" style="display: block; width: 1134px;">
    
    <div class="center_con js-center_con l" style="width: 1134px;">
        <div class="article-con">
                            <!-- 买过的阅读 -->
                <div class="map">
                    <a href="/read" target="_blank"><i class="imv2-feather-o"></i></a>
                    <a href="/read/35" target="_blank">零基础学透 TypeScript</a>
                    <a href="" target="_blank">
                        <span>
                            / 3-8 21 索引类型：获取索引类型和索引值类型
                        </span>
                    </a>
                </div>

            


            <div class="art-title" style="margin-top: 0px;">
                21 索引类型：获取索引类型和索引值类型
            </div>
            <div class="art-info">
                
                <span>
                    更新时间：2019-06-28 11:48:42
                </span>
            </div>
            <div class="art-top">
                                <img src="https://img2.mukewang.com/5d0c3ae50001b47106400359.jpg" alt="">
                                                <div class="famous-word-box">
                    <img src="https://www.imooc.com/static/img/column/bg-l.png" alt="" class="bg1 bg">
                    <img src="https://www.imooc.com/static/img/column/bg-r.png" alt="" class="bg2 bg">
                    <div class="famous-word">横眉冷对千夫指，俯首甘为孺子牛。<p class="author">——鲁迅</p></div>
                </div>
                            </div>
            <div class="art-content js-lookimg">
                <div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">我们这里要讲的，可不是前面讲接口的时候讲的索引类型。在学习接口内容的时候，我们讲过可以指定索引的类型。而本小节我们讲的索引类型包含两个内容：<strong>索引类型查询</strong>和<strong>索引访问</strong>操作符。</p>
</div><div class="cl-preview-section"><h3 id="索引类型查询操作符">3.8.1 索引类型查询操作符</h3>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;"><code>keyof</code>操作符，连接一个类型，会返回一个由这个类型的所有属性名组成的联合类型。来看例子：</p>
</div><div class="cl-preview-section"><pre class="  language-typescript"><code class="prism  language-typescript"><span class="token keyword">interface</span> <span class="token class-name">Info</span> <span class="token punctuation">{</span>
  name<span class="token punctuation">:</span> <span class="token keyword">string</span><span class="token punctuation">;</span>
  age<span class="token punctuation">:</span> <span class="token keyword">number</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">let</span> infoProp<span class="token punctuation">:</span> keyof Info<span class="token punctuation">;</span>
infoProp <span class="token operator">=</span> <span class="token string">"name"</span><span class="token punctuation">;</span>
infoProp <span class="token operator">=</span> <span class="token string">"age"</span><span class="token punctuation">;</span>
infoProp <span class="token operator">=</span> <span class="token string">"no"</span><span class="token punctuation">;</span> <span class="token comment">// error 不能将类型“"no"”分配给类型“"name" | "age"”</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">通过例子可以看到，这里的<code>keyof Info</code>其实相当于<code>"name" | “age”</code>。通过和泛型结合使用，TS 就可以检查使用了动态属性名的代码：</p>
</div><div class="cl-preview-section"><pre class="  language-typescript"><code class="prism  language-typescript"><span class="token keyword">function</span> getValue<span class="token operator">&lt;</span>T<span class="token punctuation">,</span> K <span class="token keyword">extends</span> <span class="token class-name">keyof</span> T<span class="token operator">&gt;</span><span class="token punctuation">(</span>obj<span class="token punctuation">:</span> T<span class="token punctuation">,</span> names<span class="token punctuation">:</span> K<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">:</span> T<span class="token punctuation">[</span>K<span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token comment">// 这里使用泛型，并且约束泛型变量K的类型是"keyof T"，也就是类型T的所有字段名组成的联合类型</span>
  <span class="token keyword">return</span> names<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>n <span class="token operator">=&gt;</span> obj<span class="token punctuation">[</span>n<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 指定getValue的返回值类型为T[K][]，即类型为T的值的属性值组成的数组</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> info <span class="token operator">=</span> <span class="token punctuation">{</span>
  name<span class="token punctuation">:</span> <span class="token string">"lison"</span><span class="token punctuation">,</span>
  age<span class="token punctuation">:</span> <span class="token number">18</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> values<span class="token punctuation">:</span> <span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">getValue</span><span class="token punctuation">(</span>info<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">"name"</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
values <span class="token operator">=</span> <span class="token function">getValue</span><span class="token punctuation">(</span>info<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">"age"</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// error 不能将类型“number[]”分配给类型“string[]”</span>
</code></pre>
</div><div class="cl-preview-section"><h3 id="索引访问操作符">3.8.2 索引访问操作符</h3>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">索引访问操作符也就是<code>[]</code>，其实和我们访问对象的某个属性值是一样的语法，但是在 TS 中它可以用来访问某个属性的类型：</p>
</div><div class="cl-preview-section"><pre class="  language-typescript"><code class="prism  language-typescript"><span class="token keyword">interface</span> <span class="token class-name">Info</span> <span class="token punctuation">{</span>
  name<span class="token punctuation">:</span> <span class="token keyword">string</span><span class="token punctuation">;</span>
  age<span class="token punctuation">:</span> <span class="token keyword">number</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">type</span> NameType <span class="token operator">=</span> Info<span class="token punctuation">[</span><span class="token string">"name"</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> name<span class="token punctuation">:</span> NameType <span class="token operator">=</span> <span class="token number">123</span><span class="token punctuation">;</span> <span class="token comment">// error 不能将类型“123”分配给类型“string”</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">再来看个例子：</p>
</div><div class="cl-preview-section"><pre class="  language-typescript"><code class="prism  language-typescript"><span class="token keyword">function</span> getProperty<span class="token operator">&lt;</span>T<span class="token punctuation">,</span> K <span class="token keyword">extends</span> <span class="token class-name">keyof</span> T<span class="token operator">&gt;</span><span class="token punctuation">(</span>o<span class="token punctuation">:</span> T<span class="token punctuation">,</span> name<span class="token punctuation">:</span> K<span class="token punctuation">)</span><span class="token punctuation">:</span> T<span class="token punctuation">[</span>K<span class="token punctuation">]</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> o<span class="token punctuation">[</span>name<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// o[name] is of type T[K]</span>
<span class="token punctuation">}</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">这个函数中，两个参数的类型分别为泛型 T 和 K，而函数的返回值类型为<code>T[K]</code>，只要函数的返回值也是这种形式，即访问参数 o 的参数 name 属性，即可。</p>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">最后我们来看个结合接口的例子：</p>
</div><div class="cl-preview-section"><pre class="  language-typescript"><code class="prism  language-typescript"><span class="token keyword">interface</span> <span class="token class-name">Obj</span><span class="token operator">&lt;</span>T<span class="token operator">&gt;</span> <span class="token punctuation">{</span>
  <span class="token punctuation">[</span>key<span class="token punctuation">:</span> <span class="token keyword">number</span><span class="token punctuation">]</span><span class="token punctuation">:</span> T<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> key<span class="token punctuation">:</span> keyof Obj<span class="token operator">&lt;</span><span class="token keyword">number</span><span class="token operator">&gt;</span><span class="token punctuation">;</span> <span class="token comment">// keys的类型为number</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">这里需要注意，在讲接口一节时，讲索引类型的时候我们讲过，如果索引类型为 number，那么实现该接口的对象的属性名必须是 number 类型；但是如果接口的索引类型是 string 类型，那么实现该接口的对象的属性名设置为数值类型的值也是可以的，因为数值最后还是会先转换为字符串。这里一样，如果接口的索引类型设置为 string 的话，<code>keyof Obj&lt;number&gt;</code>等同于类型<code>number | string</code>：</p>
</div><div class="cl-preview-section"><pre class="  language-typescript"><code class="prism  language-typescript"><span class="token keyword">interface</span> <span class="token class-name">Obj</span><span class="token operator">&lt;</span>T<span class="token operator">&gt;</span> <span class="token punctuation">{</span>
  <span class="token punctuation">[</span>key<span class="token punctuation">:</span> <span class="token keyword">string</span><span class="token punctuation">]</span><span class="token punctuation">:</span> T<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">let</span> key<span class="token punctuation">:</span> keyof Obj<span class="token operator">&lt;</span><span class="token keyword">number</span><span class="token operator">&gt;</span><span class="token punctuation">;</span> <span class="token comment">// keys的类型为number | string</span>
key <span class="token operator">=</span> <span class="token number">123</span><span class="token punctuation">;</span> <span class="token comment">// right</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">也可以使用访问操作符，获取索引签名的类型：</p>
</div><div class="cl-preview-section"><pre class="  language-typescript"><code class="prism  language-typescript"><span class="token keyword">interface</span> <span class="token class-name">Obj</span><span class="token operator">&lt;</span>T<span class="token operator">&gt;</span> <span class="token punctuation">{</span>
  <span class="token punctuation">[</span>key<span class="token punctuation">:</span> <span class="token keyword">string</span><span class="token punctuation">]</span><span class="token punctuation">:</span> T<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> obj<span class="token punctuation">:</span> Obj<span class="token operator">&lt;</span><span class="token keyword">number</span><span class="token operator">&gt;</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
  age<span class="token punctuation">:</span> <span class="token number">18</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> value<span class="token punctuation">:</span> Obj<span class="token operator">&lt;</span><span class="token keyword">number</span><span class="token operator">&gt;</span><span class="token punctuation">[</span><span class="token string">"age"</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// value的类型是number，也就是name的属性值18的类型</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">还有一点，我们在讲后面知识的时候会遇到，就是当tsconfig.json里<code>strictNullChecks</code>设为<code>false</code>时，通过<code>Type[keyof Type]</code>获取到的，是除去<code>never &amp; undefined &amp; null</code>这三个类型之后的字段值类型组成的联合类型，来看例子：</p>
</div><div class="cl-preview-section"><pre class="  language-typescript"><code class="prism  language-typescript"><span class="token keyword">interface</span> <span class="token class-name">Type</span> <span class="token punctuation">{</span>
  a<span class="token punctuation">:</span> never<span class="token punctuation">;</span>
  b<span class="token punctuation">:</span> never<span class="token punctuation">;</span>
  c<span class="token punctuation">:</span> <span class="token keyword">string</span><span class="token punctuation">;</span>
  d<span class="token punctuation">:</span> <span class="token keyword">number</span><span class="token punctuation">;</span>
  e<span class="token punctuation">:</span> undefined<span class="token punctuation">;</span>
  f<span class="token punctuation">:</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
  g<span class="token punctuation">:</span> object<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">type</span> test <span class="token operator">=</span> Type<span class="token punctuation">[</span>keyof Type<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// test的类型是string | number | object</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">这个例子中接口 Type 有几个属性，通过索引访问操作符和索引类型查询操作符可以选出类型不为 never &amp; undefined &amp; null 的类型。</p>
</div><div class="cl-preview-section"><h3 id="本节小结">本节小结</h3>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">本小节我们学习了两个类型操作符：索引类型查询操作符<code>keyof</code>，和索引访问操作符<code>[]</code>。通过keyof我们能够获取一个类型的所有属性名组成的联合类型，通过[]我们可以获取某个类型定义中指定字段值的类型。我们还学习了它们的组合使用方法，当tsconfig.json里<code>strictNullChecks</code>设为<code>false</code>时，我们可以通过<code>[keyof Type]</code>获取一个类型定义的所有除去<code>never &amp; undefined &amp; null</code>的字段值的类型组成的联合类型。</p>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">下个小节我们将学习一种新的复用现有类型定义，产生新类型定义的一种类型——映射类型。<br>
<img src="http://img.mukewang.com/5d034609000117cd16000300.jpg" alt="图片描述" data-original="http://img.mukewang.com/5d034609000117cd16000300.jpg" class="" style="cursor: pointer;"></p>
</div></div>
            </div>
                            <!-- 买过的阅读 -->
                <div class="art-next-prev clearfix">
                                                                        <!-- 已买且开放 或者可以试读 -->
                            <a href="/read/35/article/357">
                                                    <div class="prev l clearfix">
                                <div class="icon l">
                                    <i class="imv2-arrow3_l"></i>
                                </div>
                                <p>
                                    20 this，类型？
                                </p>
                            </div>
                        </a>
                                                                                            <!-- 已买且开放 或者可以试读 -->
                            <a href="/read/35/article/359">
                                                    <div class="next r clearfix">
                                <p>
                                    22 使用映射类型得到新的类型
                                </p>
                                <div class="icon r">
                                    <i class="imv2-arrow3_r"></i>
                                </div>

                            </div>
                        </a>
                                    </div>
                    </div>
        <div class="comments-con js-comments-con" id="coments_con">
        </div>



    </div>
    
    
    

</div>
 
<!-- 专栏介绍页专栏评价 -->

<!-- 专栏介绍页底部三条评价 -->

<!-- 专栏阅读页弹层目录和介绍页页面目录 -->

<!-- 专栏阅读页发布回复 -->

<!-- 专栏阅读页发布评论 -->

<!-- 专栏阅读页底部评论 -->

<!-- 专栏阅读 单个 评论 -->

<!-- 新增回复和展开三条以外回复 -->

<!-- 立即订阅的弹窗 -->












</div></body></html>